package com.onpositive.knowledge.model.value.audits;

import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.onpositive.data.IPropertyConstants;
import com.onpositive.semantic.model.api.property.IProperty;
import com.onpositive.units.ParsedIdent;
import com.onpositive.units.ParsedSentence;
import com.onpositive.units.ParsedString;
import com.onpositive.units.ParsedValue;
import com.onpositive.units.ParsedValueSequenceV2;
import com.onpositive.units.RangeValue;
import com.onpositive.units.Ranker;
import com.onpositive.units.ValueCluster;

public class IdentValueSplitterAudit extends AbstractUniverseAudit
{

	/**
	 * 
	 */
	private static final long serialVersionUID = 7354142792332093455L;
	/**
	 * 
	 */
	public final static String ID = "ident-split-and-sort-audit" ;
	public final static String COMMENT = "split-and-sort" ;

	@Override
	public void perform(Iterable<IProperty> properties,	Iterable<Object> objects, AbstractAuditResult auditResult)
	{	
		if( !(auditResult instanceof OwnAuditResult))
			return ;	
		
		Map<String,Object> metaInfo = new HashMap<String, Object>() ;
		metaInfo.put( "audit-result", auditResult) ;
		
		HashSet<String> singleRefs = new HashSet<String>() ; 
		metaInfo.put( "single-refs", singleRefs ) ;
		
		HashSet<ParsedValue> sentencesSet = new HashSet<ParsedValue>() ; 
		metaInfo.put( "sentences", sentencesSet ) ;
		
		HashMap<String,Integer> temporaryOrderInfo = new HashMap<String, Integer>() ;
		metaInfo.put( "order-map", temporaryOrderInfo ) ;
		
		iterateProperties(properties, objects, metaInfo, 0);
	}

	@Override
	@SuppressWarnings("unchecked")
	public void iterateProperties(Iterable<IProperty> properties, Iterable<Object> objects, Map<String,Object> metaInfo, int ind)
	{
		
		HashSet<String> singleRefs  = (HashSet<String>) metaInfo.get( "single-refs" ) ;
		HashSet<String> sentencesSet = (HashSet<String>) metaInfo.get( "sentences" ) ;
		HashMap<String,Integer> temporaryOrderInfo = (HashMap<String, Integer>) metaInfo.get("order-map") ;
		
		OwnAuditResult _res = (OwnAuditResult) metaInfo.get( "audit-result" ) ;
		for( IProperty prop : properties ){
			
			String name = prop.getMeta().getSingleValue( "id", String.class, null ) ;
//			if( !name.equals("type") )
//				continue ;
			
			Boolean isService = prop.getMeta().getSingleValue( IPropertyConstants.CHAR_IS_SERVICE_PROPERTY, Boolean.class, null) ;
			if( isService != null && isService )
				continue ;
			
			Boolean isDepricated = prop.getMeta().getSingleValue( IPropertyConstants.CHAR_DEPRICATED_LABEL, Boolean.class, null);
			if( isDepricated != null && isDepricated )
				continue ;
			
			Boolean isIdent = prop.getMeta().getSingleValue( IPropertyConstants.CHAR_IS_IDENTIFICATOR, Boolean.class, null);
			if( isIdent != null && !isIdent )
				continue ;			
			
			singleRefs.clear() ;
			sentencesSet.clear() ;
			temporaryOrderInfo.clear() ;
			iterateObjects( prop, objects, metaInfo, ind );			
			
			processLinks( prop, metaInfo ) ;
			_res.setLooksApplyable(true) ;
		}
	}
	
	InSentenceIdentComparator inSentenceIdentComparator ;
	IdentComparator identComparator ;
	
	@SuppressWarnings("unchecked")
	private void processLinks( IProperty prop, Map<String,Object> metaInfo ) {		
		
		HashSet<String> singleRefs  = (HashSet<String>) metaInfo.get( "single-refs" ) ;
		HashSet<ParsedValue> sentencesSet = (HashSet<ParsedValue>) metaInfo.get( "sentences" ) ;
		OwnAuditResult result = (OwnAuditResult) metaInfo.get("audit-result") ;		
				
		HashMap<String,ParsedValue[]> correctionMap = result.getCorrectionsMapForCompletion( prop.getId() ) ;
			
		HashMap<String,Integer> incidencyInfo = (HashMap<String, Integer>) metaInfo.get("order-map") ;

//		for( ParsedValue pv : sentencesSet )
//		{
//			if(!(pv instanceof ParsedSentence))
//				continue ;
//			
//			ParsedSentence sentence = (ParsedSentence) pv ;			
//			collectOrderInfo( sentence, singleRefs, temporaryOrderInfo ) ;
//		}
		HashMap<String,Integer> weightsMap = result.getWeightsMapForCompletion( prop.getId() ) ;
		constructOrderMap( incidencyInfo, weightsMap, prop.getId() ) ;
		
		inSentenceIdentComparator = new InSentenceIdentComparator(weightsMap) ;
		identComparator = new IdentComparator(weightsMap) ;
		
		for( ParsedValue pv : sentencesSet )
		{
			if(!(pv instanceof ParsedSentence))
				continue ;
			
			ParsedSentence sentence = (ParsedSentence) pv ;			
			ParsedValue[] lst = splitAndSort( sentence, singleRefs, weightsMap, true ) ;
			if( lst != null && lst.length != 0 )
				correctionMap.put( sentence.getContentString(), lst ) ;
		}		
	}
	private ParsedValue[] splitAndSort(
			ParsedSentence sentence,
			HashSet<String> singleRefs,
			HashMap<String, Integer> orderMap,
			boolean doSort )
	{
		ParsedValue[] valArray = sentence.getValuesArray() ;
		int l = valArray.length ;
		if( l < 2 )
			return null ;
		
		ArrayList<Integer> piecesOffsets = new ArrayList<Integer>() ;
		ArrayList<ParsedValue> result_ = new ArrayList<ParsedValue>() ;
		
		boolean gotChange = false ;
		
		int[] marks = mark( valArray, singleRefs ) ;		
		extractSingleRefs( valArray, piecesOffsets, result_, marks ) ;
		
		gotChange = result_.size() != 0 ;		
		
		boolean c1 = extractSentences( valArray, result_, piecesOffsets, orderMap ) ;
		
		gotChange = gotChange || c1 ;
		
		ArrayList<ParsedValue> result_unsorted = new ArrayList<ParsedValue>(result_) ;		
		Collections.sort( result_, identComparator ) ;
		
		gotChange = gotChange || result_.equals(result_unsorted) ;
		
		if(!gotChange)
			return null ;
		
		ParsedValue[] result = killParasiteStrings(result_.toArray( new ParsedValue[result_.size()]) ) ;
		
		return result ;
	}
	
	public final static ParsedValue[] killParasiteStrings(	ParsedValue[] array) {
		
		int l = array.length ;
		if( l == 0 )
			return array ;
		
		int start = 0 ;
		ParsedValue first = array[0] ;
		if( isBadValue(first) )
			start++ ;

		int end = l ;
		ParsedValue last = array[l-1] ;
		if( isBadValue(last) )
			end-- ;
		
		int l0 = end-start;
		if( l0 <= 0 )
			return new ParsedValue[]{} ;
		
		ParsedValue[] result = new ParsedValue[l0] ;
		System.arraycopy(array, start, result, 0, l0 ) ;
		
		return result ;
	}

	public final static boolean isBadValue( ParsedValue pv ) {
		
		if( !(pv instanceof ParsedString) )
			return false ;
		
		ParsedString ps = (ParsedString) pv ;
		String value = ps.getValueAsString() ;
		if( value.length() < 2  )
			return true ;
		
		if( value.replaceAll("[^0-9a-zA-Z]", "").trim().length() < 2 )
			return true ;
		
		return false;
	}

	public static final class IdentComparator implements Comparator<ParsedValue> {
		
		
		public IdentComparator( Map<String,Integer> weights ){
			this.weights = weights ;
		}
		private final Map<String,Integer> weights ;
		
		@Override
		public int compare(ParsedValue o1, ParsedValue o2) {
			
			int w1 = computeWeight( o1 );				
			int w2 = computeWeight( o2 );
			
			return w1-w2;
		}

		private int computeWeight(ParsedValue o1) {
			
			int weight = -1 ;
			
			ParsedIdent ident = extractIdent( o1 ) ;
			if( ident != null ){
				String ref = ident.getRef() ;
				
				if( ref != null ){
					Integer weight_tmp = weights.get(ref) ;
					if( weight_tmp != null )
						weight = weight_tmp ;
				}
			}
			return weight;
		}

		@SuppressWarnings("unchecked")
		private ParsedIdent extractIdent( ParsedValue val ) {
			
			if( val instanceof ParsedIdent )
				return (ParsedIdent) val ;
			
			if( val instanceof ValueCluster ){
				ValueCluster<?> vc = (ValueCluster<?>) val ;
				Class<?> clazz = ((ValueCluster<?>) val).getTargetClass() ;
				
				if( !(clazz == ParsedIdent.class) )
					return null;
				
				ValueCluster<ParsedIdent> identCluster = (ValueCluster<ParsedIdent>) vc ;
				ParsedIdent pi = identCluster.getTargetValue() ;
				
				return pi ;
			}
			else if ( val instanceof ParsedSentence )
			{
				ParsedSentence ps = (ParsedSentence) val ;				
				ParsedValue[] valArr = ps.getValuesArray() ;
				for( ParsedValue pv : valArr )
					if( pv instanceof ParsedIdent )
						return (ParsedIdent) pv ;	
			
			return null;
			}
			return null ;
		}
	};
	
	private static final class InSentenceIdentComparator implements Comparator<ParsedIdent> {
		
		
		private InSentenceIdentComparator( Map<String,Integer> weights ){
			this.weights = weights ;
		}
		private final Map<String,Integer> weights ;
		
		@Override
		public int compare(ParsedIdent o1, ParsedIdent o2) {
			
			int w1= -1 ;
			int w2= -1 ;
			
			String ref1 = o1.getRef() ;
			String ref2 = o2.getRef() ;
			
			Integer w1_ = weights.get(ref1);
			Integer w2_ = weights.get(ref2);
			
			if( w1_ != null )
				w1 = w1_ ;
			
			if( w2_ != null )
				w2 = w2_ ;
			
			return w1 - w2;
		}
	};
	
	private boolean extractSentences( ParsedValue[] valArray, ArrayList<ParsedValue> srArray, ArrayList<Integer> piecesOffsets, HashMap<String, Integer> orderMap)
	{
		boolean gotChanges = false ;
		ArrayList<ParsedValue> sentenceBuf = new ArrayList<ParsedValue>() ;
		ArrayList<ParsedIdent> identBuf = new ArrayList<ParsedIdent>() ;
		ArrayList<ParsedIdent> identBuf_tmp = new ArrayList<ParsedIdent>() ;
		
		for( int i = 0 ; i < piecesOffsets.size() ; i+=2 ){
			
			int lb = piecesOffsets.get( i ) ;
			int ub = piecesOffsets.get(i+1) ;
			if( lb == ub )
				continue ;
			
			sentenceBuf.clear() ;
			identBuf.clear() ;
			for( int j = lb ; j < ub ; j++ ){
				ParsedValue pv = valArray[j] ;
				if( pv instanceof ParsedIdent )
					identBuf.add( (ParsedIdent) pv ) ;
				
				else{
					if( !identBuf.isEmpty() ){
						
						identBuf_tmp.clear() ;
						identBuf_tmp.addAll(identBuf) ;
						
						Collections.sort( identBuf, inSentenceIdentComparator ) ;
						sentenceBuf.addAll(identBuf) ;
						
						gotChanges = gotChanges || !identBuf.equals(identBuf_tmp) ;						
						identBuf.clear() ;
					}
					sentenceBuf.add(pv) ;
				}
			}
			if( !identBuf.isEmpty() ){
				identBuf_tmp.clear() ;
				identBuf_tmp.addAll(identBuf) ;
				
				Collections.sort( identBuf, inSentenceIdentComparator ) ;
				sentenceBuf.addAll(identBuf) ;
				
				gotChanges = gotChanges || !identBuf.equals(identBuf_tmp) ;						
				identBuf.clear() ;
			}
			
			ParsedValue[] arr = sentenceBuf.toArray( new ParsedValue[sentenceBuf.size()] ) ;
			ParsedValue[] result = killParasiteStrings( arr ) ;
			srArray.add( new ParsedSentence( result, ID, null ) ) ;			
		}
		return gotChanges ;
	}

	private void extractSingleRefs(ParsedValue[] valArray, ArrayList<Integer> piecesOffsets, ArrayList<ParsedValue> srArray, int[] marks )
	{
		int leftBound = 0 ;
		int rightBound = 0 ;
		
		int l = valArray.length;
		ArrayList<ParsedValue> clusterBuf = new ArrayList<ParsedValue>() ;
		for( int i = 0 ; i < l ; i++ ){
			
			if( marks[i] != MARK_SINGLE_REF ){
				
				if( marks[i] == MARK_NONSINGLE_REF ){
					for(  ; i < l-1 && marks[i+1] == MARK_STRING ; i++ ) ;
						rightBound = i+1 ;
				}
				else if( marks[i] == MARK_OTHER )
					rightBound = i+1 ;
				
				continue ;
			}
			
			if( i > 0 && marks[i-1] == MARK_NONSINGLE_REF )
				continue ;
			
			if( i < l-1 && marks[i+1] == MARK_NONSINGLE_REF )
				continue ;
			
			piecesOffsets.add( leftBound ) ;
			piecesOffsets.add( rightBound ) ;
			
			clusterBuf.clear() ;
			for( int j = rightBound ; j < i ; j++ )
				clusterBuf.add( valArray[j] ) ;
			
			if( !clusterBuf.isEmpty() && isBadValue( clusterBuf.get(0) ) )
				clusterBuf.remove(0) ;			
			
			int targetInd = clusterBuf.size() ;
			
			ParsedValue pv = valArray[i] ;
			int shift = 0 ;
			if( pv instanceof ValueCluster ){
				
				ValueCluster<?> vc = (ValueCluster<?>)pv;
				shift = ValueCluster.computeTargetInd(vc) ;
				
				ParsedValue[] clusterArray = vc.getValuesArray() ;
				for( int j = 0 ; j < clusterArray.length ; j++ )
					clusterBuf.add( clusterArray[j] ) ;				
			}
			else
				clusterBuf.add(pv) ;
				
			 targetInd += shift ;
			
			for( leftBound = i+1 ; leftBound < l ; leftBound++ )
			{
				if( marks[leftBound] == MARK_STRING )
					clusterBuf.add( valArray[leftBound]) ;
				else
					break ;
			}
			rightBound = leftBound ;
			i = leftBound-1 ;
			
			int s = clusterBuf.size() ;
			if( s == 1 )
				srArray.add( clusterBuf.get(0) ) ;
			else{				
				if( isBadValue( clusterBuf.get(s-1) ) )
					clusterBuf.remove(s-1) ;	
				
				ParsedValue[] array = clusterBuf.toArray( new ParsedValue[ clusterBuf.size() ]);
				srArray.add( new ValueCluster<ParsedIdent>( array, ParsedIdent.class, targetInd, ID, null ) ) ;
			}
		}
		
		piecesOffsets.add( leftBound ) ;
		piecesOffsets.add( l ) ;	
	}

	private static final int MARK_STRING = 0 ;
	private static final int MARK_OTHER = 1 ;
	private static final int MARK_SINGLE_REF = 2 ;
	private static final int MARK_NONSINGLE_REF = 3 ;
	
	private int[] mark(ParsedValue[] valArray, HashSet<String> singleRefs) {
		
		int[] marks = new int[valArray.length] ;
		
		for( int i = 0 ; i < valArray.length ; i++ ){
			
			ParsedValue pv = valArray[i] ;
			ParsedIdent pIdent = null ;
			
			if( pv instanceof ParsedString ){
				marks[i] = MARK_STRING ;
				continue ;
			}
			else if( pv instanceof ParsedIdent )
				pIdent = (ParsedIdent) pv ;				
			
			else if( pv instanceof ValueCluster<?> )
			{
				ValueCluster<?> vc = (ValueCluster<?>) pv ;
				Class<?> clazz = ((ValueCluster<?>) pv).getTargetClass() ;
				
				if( clazz == ParsedIdent.class )
					pIdent = (ParsedIdent) vc.getTargetValue() ;
			}
			if( pIdent == null ){
				marks[i] = MARK_OTHER ;
				continue ;
			}
			
			String ref = pIdent.getRef() ;
			if( singleRefs.contains(ref) )
				marks[i] = MARK_SINGLE_REF ;
			else
				marks[i] = MARK_NONSINGLE_REF ;			
		}
		return marks;
	}

	

	
	private void constructOrderMap(	HashMap<String,Integer> temporaryOrderInfo, HashMap<String,Integer> weightsMap, String propName )
	{
		HashSet<String> keySet = new HashSet<String>() ;
		
		for( String str : temporaryOrderInfo.keySet() ){
			int ind = str.indexOf(KEY_SEPARATOR) ;			
			String s0 = str.substring(0, ind).trim();
			String s1 = str.substring(ind+ KEY_SEPARATOR.length()).trim();
			
			if( s0.equals(s1) )
				continue ;
			
//			String inverseKey = s1 + KEY_SEPARATOR + s0 ;
//			if( temporaryOrderInfo.get(inverseKey) == null )
//				continue ;
			
			keySet.add(s0) ;			
			keySet.add(s1 ) ;
		}
		
		if( keySet.size() == 0 )
			return ;
		
		ArrayList<String> keysArray = new ArrayList<String>( keySet ) ;
		Collections.sort( keysArray );
		HashMap<String,Integer> indMap = new HashMap<String, Integer>() ;
		int size = keysArray.size();
		for( int i = 0 ; i < size ; i++ )
			indMap.put( keysArray.get(i), i ) ;
		
		double[] matrix = new double[size*size] ;
		
		for( int i = 0 ; i < matrix.length ; i++ )
			matrix[i] = 0 ;
		
		for( Map.Entry<String, Integer> entry : temporaryOrderInfo.entrySet() ){
			
			String key = entry.getKey() ;
			int ind = key.indexOf(KEY_SEPARATOR) ;
			String s0 = key.substring(0, ind).trim() ;
			if( !keySet.contains(s0) )
				continue ;
			
			String s1 = key.substring(ind+ KEY_SEPARATOR.length()).trim() ;
			if( !keySet.contains(s1) )
				continue ;
			
			if( s0.equals(s1) )
				continue ;
			
//			String inverseKey = s1 + KEY_SEPARATOR + s0 ;
//			if( temporaryOrderInfo.get(inverseKey) == null )
//				continue ;
			
			Integer i0 = indMap.get(s0) ;
			Integer i1 = indMap.get(s1) ;
			
			Integer val = entry.getValue() ;
			if( val == null )
				continue ;
			
			matrix[ size*i0 + i1 ] = val.doubleValue() ;
			
//			if( matrix[ size*i0 + i1 ] < val.doubleValue() ){
//				matrix[ size*i1 + i0 ] = val.doubleValue() ;
//				matrix[ size*i0 + i1 ] = 0 ;
//			}
	
		}
				
		final double[] doubleRanks = Ranker.computeRanks( matrix, size ) ;
		final HashMap<String,Double> compMap = new HashMap<String, Double>() ;
		for( int i = 0 ; i < keysArray.size() ; i++ ){
			String key = keysArray.get(i) ;
			double weight = doubleRanks[i] ; 
			compMap.put(key, weight ) ;
		}
		
		
		Collections.sort( keysArray, new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				
				double d = compMap.get(o1) - compMap.get(o2) ;
				double abs = Math.abs(d) ;
				if( abs < 1.0 ){
					d /= abs ;
					d *= 2 ;
				}
				return (int) d;
			}			
		}) ;		
		
		for( int i = 0 ; i < keysArray.size() ; i++ ){
			String key = keysArray.get(i) ;
			double weight = doubleRanks[i] ;
			weightsMap.put(key, i ) ;
			System.out.println( key +": " + i + ": " + compMap.get(key) ) ;			
		}
		System.out.println() ;		
	}

	
	private static final String KEY_SEPARATOR = "_#_#_" ;
	
	@Override
	public AbstractAuditResult createAuditResult() {
		return new OwnAuditResult( this );
	}

	@Override
	public String getId() {
		return ID;
	}

	@Override
	@SuppressWarnings("unchecked")
	protected void process( IProperty prop, Object val, Map<String,Object> metaInfo, int index)
	{		
		HashSet<String> singleRefs  = (HashSet<String>) metaInfo.get( "single-refs" ) ;
		HashSet<ParsedValue> sentencesSet = (HashSet<ParsedValue>) metaInfo.get( "sentences" ) ;
		
		if( val instanceof ParsedIdent ){
			ParsedIdent pi = (ParsedIdent) val ;
			singleRefs.add( pi.getRef() ) ;
		}
		else if( val instanceof ValueCluster ){
			ValueCluster<?> vc = (ValueCluster<?>) val ;
			Class<?> clazz = ((ValueCluster<?>) val).getTargetClass() ;
			
			if( !(clazz == ParsedIdent.class) )
				return ;
			
			ValueCluster<ParsedIdent> identCluster = (ValueCluster<ParsedIdent>) vc ;
			ParsedIdent pi = identCluster.getTargetValue() ;
			
			singleRefs.add( pi.getRef() ) ;
		}
		
		else if ( val instanceof ParsedValueSequenceV2 )
		{
			ParsedValueSequenceV2 valSeq = (ParsedValueSequenceV2) val ;
			if( index == 0 )
			{
				HashMap<String,Integer> temporaryOrderInfo = (HashMap<String, Integer>) metaInfo.get("order-map") ;			
				
				ParsedValue[] underSet = valSeq.getUnderlyingTermArray() ;
				ParsedIdent prevIdent = null ;
				for( ParsedValue pv : underSet ){
					if( pv instanceof ParsedIdent ){
						if( prevIdent != null ){
							String s1 = ((ParsedIdent)pv).getRef() ;
							if( s1 == null )
								continue ;

							String s0 = prevIdent.getRef() ;

							if( s0 != null ){		
								String key = s0 + KEY_SEPARATOR + s1 ;
								Integer count = temporaryOrderInfo.get(key) ;
								if( count == null )
									count = 0 ;

								count++ ;
								temporaryOrderInfo.put(key, count) ;
								
								String inverseKey = s1 + KEY_SEPARATOR + s0 ;
								Integer inverseCount = temporaryOrderInfo.get( inverseKey ) ;
								if( inverseCount == null )
									continue ;
								
								singleRefs.add(s0) ;
								singleRefs.add(s1) ;								
							}
						}
						prevIdent = (ParsedIdent) pv ;					
					}
					else if( pv instanceof RangeValue )
						prevIdent = null ;
				}
			}
			
			if( val instanceof ParsedSentence )
			{				
				ParsedSentence ps = (ParsedSentence) val ;
				sentencesSet.add( ps ) ;				
			}
			else{
				ParsedValue[] values = valSeq.getValuesArray() ;
				iterateValues(prop, values, false, metaInfo, 1) ;
			}
		}
	}

	protected Class<?>[] createNecessaryClasses() {
		return new Class<?>[]{ ParsedValueSequenceV2.class, ParsedIdent.class };
	}

	protected Class<?>[] createTargetClasses() {
		return new Class<?>[]{ ParsedValueSequenceV2.class, ParsedIdent.class };
	}
	
	
	public static class OwnAuditResult extends AbstractAuditResult {
		
		
		/**
		 * 
		 */
		private static final long serialVersionUID = 6960573255146914190L;


		public OwnAuditResult( IUniverseAudit audit )
		{
			super( audit);
		}

		public OwnAuditResult( IProperty prop )
		{
			super( prop );
		}

		final HashMap<String, HashMap<String,ParsedValue[]>> correctionsMap = new HashMap<String,HashMap<String, ParsedValue[]>>() ;
		final HashMap<String, HashMap<String,Integer>> weightsMap = new HashMap<String,HashMap<String, Integer>>() ;

		private HashMap<String, ParsedValue[]> getCorrectionsMapForCompletion( String str )
		{
			HashMap<String, ParsedValue[]> map = correctionsMap.get(str);
			if( map == null )
			{
				map = new HashMap<String,ParsedValue[]>() ;
				correctionsMap.put(str,map) ;
			}
			return map;
		}

		public HashMap<String, ParsedValue[]> getCorrectionsMap( String str )
		{
			return correctionsMap.get(str);
		}
		
		private HashMap<String, Integer> getWeightsMapForCompletion( String str )
		{
			HashMap<String, Integer> map = weightsMap.get(str);
			if( map == null )
			{
				map = new HashMap<String,Integer>() ;
				weightsMap.put(str,map) ;
			}
			return map;
		}
		
		public HashMap<String, Integer> getWeightsMap( String str )
		{
			return weightsMap.get(str);
		}
	}


	@Override
	public Set<String> getRequiredAudits() {
		// TODO Auto-generated method stub
		return null;
	}

}
